package com.xxx;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 1、构建管道
 * 2、获取代理对象
 * 3、完成RPC调用
 * 服务端流式响应通信方式
 * 异步方式
 * 业务场景：股票大盘，client给一个股票代码，server端不断地给出每一个时刻的股票情况
 */
public class GrpcClient4 {
    public static void main(String[] args) {
        // 1.创建通信的管道
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9000).usePlaintext().build();
        try {
            // 2.获取代理对象 stub
            HelloServiceGrpc.HelloServiceStub helloServiceStub = HelloServiceGrpc.newStub(managedChannel);
            // 3.完成RPC调用
            // 3.1准备参数
            HelloProto.HelloRequest.Builder builder = HelloProto.HelloRequest.newBuilder();
            builder.setName("xxx");
            HelloProto.HelloRequest helloRequest = builder.build();
            // 3.2进行功能RPC调用 获取响应内容
            helloServiceStub.c2ss(helloRequest, new StreamObserver<HelloProto.HelloResponse>() {
                // 自定义个成员变量 保存每一次的响应结果
                private List<HelloProto.HelloResponse> results = new ArrayList<>();

                /**
                 * 服务端每响应一次就处理一次，即服务端每掉一次onNext()方法就会处理一次
                 * @param helloResponse
                 */
                @Override
                public void onNext(HelloProto.HelloResponse helloResponse) {
                    // 服务端每响应一次就处理一次业务
                    System.out.println("服务端每一次响应的信息: " + helloResponse.getResult());
                    results.add(helloResponse);
                }

                @Override
                public void onError(Throwable throwable) {

                }

                /**
                 * 服务端所有响应结束后 再进行统一的处理 即服务端调用onCompleted方法后再进行处理
                 * 如果需要拿到响应数据 这个时候需要在onNext()方法中对每一次响应结果进行缓存起来
                 */
                @Override
                public void onCompleted() {
                    System.out.println("服务端响应结束，统一处理所有的响应内容: " + results.size());
                }
            });
            // 因为是异步监听的情况，所以需要让客户端等待服务端的响应结果
            managedChannel.awaitTermination(12, TimeUnit.SECONDS);
        } catch (Exception e) {
            throw new RuntimeException();
        } finally {
            // 关闭通道
            managedChannel.shutdown();
        }
    }
}
